// 定义 Vue 类
class Vue {
    constructor(options) {
        this.$options = options;
        this.$data = options.data;

        // 进行数据劫持
        this.observe(this.$data);

        // 代理数据到 Vue 实例上
        Object.keys(this.$data).forEach(key => {
            this._proxy(key);
        });

        // 调用 mounted 钩子
        if (options.mounted) {
            options.mounted.call(this);
        }
    }

    observe(data) {
        if (!data || typeof data !== 'object') return;
        
        // 遍历对象的所有属性
        Object.keys(data).forEach(key => {
            this.defineReactive(data, key, data[key]);
        });
    }

    defineReactive(data, key, val) {
        const dep = new Dep();
        
        Object.defineProperty(data, key, {
            enumerable: true,
            configurable: true,
            get() {
                // 依赖收集
                if (Dep.target) {
                    dep.addSub(Dep.target);
                }
                return val;
            },
            set(newVal) {
                if (val === newVal) return;
                val = newVal;
                // 通知所有订阅者
                dep.notify();
            }
        });
    }

    _proxy(key) {
        Object.defineProperty(this, key, {
            enumerable: true,
            configurable: true,
            get: () => this.$data[key],
            set: val => {
                this.$data[key] = val;
            }
        });
    }
}

// 依赖收集器
class Dep {
    constructor() {
        this.subs = [];
    }

    addSub(sub) {
        this.subs.push(sub);
    }

    notify() {
        this.subs.forEach(sub => {
            sub.update();
        });
    }
}

Dep.target = null;

// 观察者
class Watcher {
    constructor(vm, key, cb) {
        this.vm = vm;
        this.key = key;
        this.cb = cb;
        this.value = this.get();
    }

    get() {
        Dep.target = this;
        const value = this.vm[this.key];
        Dep.target = null;
        return value;
    }

    update() {
        const oldValue = this.value;
        this.value = this.get();
        this.cb.call(this.vm, this.value, oldValue);
    }
}

// 使用示例
const vm = new Vue({
    data: {
        message: 'Hello Vue!',
        count: 0
    },
    mounted() {
        // 创建一个 watcher 来监听 message 的变化
        new Watcher(this, 'message', (newVal, oldVal) => {
            console.log(`message changed from ${oldVal} to ${newVal}`);
        });

        // 创建一个 watcher 来监听 count 的变化
        new Watcher(this, 'count', (newVal, oldVal) => {
            console.log(`count changed from ${oldVal} to ${newVal}`);
        });

        // 修改数据，触发更新
        setTimeout(() => {
            this.message = 'Hello World!';
            this.count++;
        }, 1000);
    }
});